<template>
  <div class="app-container">
    <!-- Query -->
    <el-form ref="queryFormRef" :model="queryForm" :inline="true">
      <el-form-item prop="deptName" label="部门名称">
        <el-input v-model="queryForm.deptName" placeholder="请输入部门名称" @press-enter="handleQuery" />
      </el-form-item>
      <el-form-item prop="username" label="用户名称">
        <el-input v-model="queryForm.username" placeholder="请输入用户名称" @press-enter="handleQuery" />
      </el-form-item>
      <el-form-item prop="phone" label="手机号码">
        <el-input v-model="queryForm.phone" placeholder="请输入用户手机号" @press-enter="handleQuery" />
      </el-form-item>
      <el-form-item prop="status" label="用户状态">
        <el-select v-model="queryForm.status" placeholder="请选择用户状态" :style="{ width: '205px' }">
          <el-option value="2">正常</el-option>
          <el-option value="1">停用</el-option>
        </el-select>
      </el-form-item>

      <el-divider direction="vertical" :style="{ height: '30px' }" />
      <el-form-item class="form-action">
        <el-space size="default">
          <el-button v-has="'admin:sysUser:query'" type="primary" @click="handleQuery" icon="Search">搜索</el-button>
          <el-button @click="handleResetQuery" icon="Refresh"> 重置</el-button>
        </el-space>
      </el-form-item>
    </el-form>

    <!-- divider -->
    <el-divider />

    <!-- Table -->
    <el-row>
      <el-col :span="4">
        <!-- tree组件只在组件第一次渲染时展开，此处等待数据加载完成再渲染组件 -->
        <tree-dept v-if="treeDeptData" :data="treeDeptData" @node-click="getSysUserInfo" />
      </el-col>
      <el-col :span="20">
        <!-- Action -->
        <el-space class="action">
          <el-button v-has="'admin:sysUser:add'" type="primary" @click="handleAdd" datel-test="newUser" icon="Plus">
            新增</el-button>
          <el-button v-has="'admin:sysUser:remove'" type="primary" status="danger" icon="Delete" @click="
              () => {
                deleteVisible = true;
              }
            ">批量删除</el-button>
        </el-space>

        <el-table :data="tableData" row-key="userId" table-layout="auto">
          <el-table-column label="编号" prop="userId"></el-table-column>
          <el-table-column label="登录名" prop="username"></el-table-column>
          <el-table-column label="昵称" prop="nickName"></el-table-column>
          <el-table-column label="部门" prop="deptName">
            <template #default="scope">
              {{ scope.row.dept.deptName }}
            </template>
          </el-table-column>
          <el-table-column label="手机号" prop="phone"></el-table-column>
          <el-table-column label="状态" prop="status">
            <template #default="scope">
              <el-switch v-model="scope.row.status" active-value="2" inactive-value="1"
                @change="handleSwitchChange(scope.row)" />
            </template>
          </el-table-column>
          <el-table-column label="创建时间" prop="createdAt">
            <template #default="scope">
              {{ parseTime(scope.row.createdAt) }}
            </template>
          </el-table-column>
          <el-table-column label="操作" prop="action">
            <template #default="scope">
              <el-button v-has="'admin:sysUser:edit'" text type="primary" icon="Edit" @click="handleUpdate(scope.row)">
                修改
              </el-button>
              <el-button v-has="'admin:sysUser:edit'" text type="primary" icon="Delete"
                @click="handleDelete(scope.row)">删除</el-button>

              <el-button v-has="'admin:sysUser:resetPassword'" text type="primary" icon="Refresh"
                @click="handleReset(scope.row.userId)">重置</el-button>
            </template>
          </el-table-column>
        </el-table>

        <el-pagination :page-size="10" v-model="currentPage" layout="prev, pager, next" :total="pager.count"
          @current-change="handlePageChange" />
      </el-col>
    </el-row>

    <!-- Modal -->
    <el-dialog v-model="modalVisible" :title="modalTitle" title-align="start" :width="600" @cancel="handleModalCancel()"
      @before-ok="handleBeforeOk">
      <el-form ref="modalFormRef" :model="modalForm" :rules="rules" auto-label-width>
        <el-row :gutter="16">
          <el-col :span="12">
            <el-form-item prop="nickName" label="用户昵称">
              <el-input v-model="modalForm.nickName" placeholder="请输入用户昵称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="deptId" label="所属部门">
              <el-tree-select v-model="modalForm.deptId" :data="treeDeptData"
                :props="{ key: 'deptId', label: 'deptName',value:'deptId' }" placeholder="请选择所属部门" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="phone" label="手机号码">
              <el-input v-model="modalForm.phone" placeholder="请输入手机号码" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="email" label="邮箱">
              <el-input v-model="modalForm.email" placeholder="请输入邮箱" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="username" label="用户名称">
              <el-input v-model="modalForm.username" placeholder="请输入用户名称" />
            </el-form-item>
          </el-col>
          <el-col v-if="!modalForm.userId" :span="12">
            <el-form-item prop="password" label="用户密码">
              <el-input v-model="modalForm.password" type="password" placeholder="请输入用户密码" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="sex" label="用户性别">
              <el-select v-model="modalForm.sex" placeholder="请选择用户性别">
                <el-option value="0"> 男 </el-option>
                <el-option value="1"> 女 </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="status" label="状态">
              <el-radio-group v-model="modalForm.status">
                <el-radio label="2"> 正常 </el-radio>
                <el-radio label="1"> 停用 </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="postId" label="岗位">
              <el-select v-model="modalForm.postId" placeholder="请选择岗位">
                <el-option v-for="item in postList" :key="item.postId" :value="item.postId" :label="item.postName" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="roleId" label="角色">
              <el-select v-model="modalForm.roleId" placeholder="请选择角色">
                <el-option v-for="item in roleList" :key="item.roleId" :value="item.roleId" :label="item.roleName" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item prop="remark" label="备注">
          <el-input type="textarea" placeholder="请输入备注" allow-clear />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-row justify="end">
          <el-button @click="handleModalCancel">取消</el-button>
          <el-button type="primary" @click="handleBeforeOk">确认</el-button>
        </el-row>
      </template>
    </el-dialog>

    <el-dialog v-model="resetPwdVisible" title="重置密码" @before-ok="handleResetPwd"
      @cancel="resetPwdFormRef.resetFields()">
      <el-form ref="resetPwdFormRef" :model="resetPwdForm" :rules="resetPwdRules" auto-label-width>
        <el-form-item prop="password" label="新密码">
          <el-input v-model="resetPwdForm.password" type="password" placeholder="请输入新密码" />
        </el-form-item>
        <el-form-item prop="repeatPwd" label="确认密码">
          <el-input v-model="resetPwdForm.repeatPwd" type="password" placeholder="请输入确认密码" />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-row justify="end">
          <el-button @click="resetPwdFormRef.resetFields();resetPwdVisible=false;">取消</el-button>
          <el-button type="primary" @click="handleResetPwd">确认</el-button>
        </el-row>
      </template>
    </el-dialog>

    <!-- Akiraka 20230223 删除与批量删除 开始 -->
    <DeleteModal :data="deleteData" :visible="deleteVisible" :apiDelete="removeUser"
      @deleteVisibleChange="() => (deleteVisible = false)" />
    <!-- Akiraka 20230223 删除与批量删除 结束 -->
  </div>
</template>

<script setup>
import { reactive, ref, getCurrentInstance, onMounted, watch } from "vue";
import TreeDept from "./components/TreeDept.vue";
import {
  getUser,
  addUser,
  updateUser,
  removeUser,
  updateUserStatus,
  resetUserPwd,
} from "@/api/admin/sys-user";
import { getRole } from "@/api/admin/role";
import { getPost } from "@/api/admin/post";
import { getDept } from "@/api/admin/sys-dept";
import { parseTime } from "@/utils/parseTime";

// Akiraka 20230210 删除数据
const deleteData = ref([]);
// Akiraka 20230210 删除对话框
const deleteVisible = ref(false);
// Akiraka 20230210 监听删除事件
const resetPwdFormRef = ref({});
const queryFormRef = ref({});
const modalFormRef = ref({});
watch(
  () => deleteVisible.value,
  (value) => {
    if (value == false) {
      getSysUserInfo({ ...pager, ...queryForm });
    }
  }
);

const { proxy } = getCurrentInstance();

// Query
const { queryForm, handleQuery, handleResetQuery } = useQueryData();
// ApiInfo
const {
  currentPage,
  getSysPostInfo,
  getSysRoleInfo,
  getSysDeptTreeInfo,
  getSysUserInfo,
} = useApiInfo();

// Pager
const pager = reactive({
  count: 0,
  pageIndex: 1,
  pageSize: 10,
});

// Reset Pwd
const {
  resetPwdForm,
  resetPwdVisible,
  resetPwdRules,
  handleReset,
  handleResetPwd,
} = useResetPwd();

// Table Operate
const {
  columns,
  tableData,
  treeDeptData,
  roleList,
  postList,
  handlePageChange,
  handlePageSizeChange,
  handleSwitchChange,
} = useTableList();

// ModalForm Operate
const {
  rules,
  modalForm,
  modalVisible,
  modalTitle,
  handleAdd,
  handleUpdate,
  handleBeforeOk,
  handleModalCancel,
} = useModalOperate();

function useQueryData() {
  const queryForm = reactive({});

  // 查询
  const handleQuery = () => {
    getSysUserInfo(queryForm);
  };

  // 重置查询
  const handleResetQuery = () => {
    queryFormRef.value.resetFields();

    getSysUserInfo(queryForm);
  };

  return { queryForm, handleQuery, handleResetQuery };
}

function useResetPwd() {
  const resetPwdVisible = ref(false);
  const resetPwdForm = reactive({});

  // Rules
  const resetPwdRules = {
    password: [{ required: true, message: "请输入密码" }],
    repeatPwd: [
      {
        required: true,
        message: "请重复输入密码",
      },
      {
        validator: (value, cb) => {
          if (value !== resetPwdForm.password) {
            cb("两次输入的密码不一致");
          }
        },
      },
    ],
  };

  // 用户重置密码API参数
  const resetParams = {};

  // 重置
  const handleReset = (userId) => {
    resetPwdVisible.value = true;
    resetParams.userId = userId;
  };

  // 重置用户密码
  const handleResetPwd = (done) => {
    resetPwdFormRef.value.validate(async (err) => {
      if (!err) {
        resetParams.password = resetPwdForm.password;
        const { msg } = await resetUserPwd(resetParams);
        proxy.$message.success(msg);
        done();
        getSysUserInfo();
      } else {
        done(false);
      }
    });
  };

  return {
    resetPwdForm,
    resetPwdVisible,
    resetPwdRules,
    handleReset,
    handleResetPwd,
  };
}

function useApiInfo() {
  const currentPage = ref(1);
  /**
   * 获取用户信息
   * @param {*} [params]
   */
  const getSysUserInfo = async (params = {}) => {
    const { data, code, msg } = await getUser(params);
    if (code == 200) {
      tableData.value = data.list;
      Object.assign(pager, {
        count: data.count,
        pageIndex: data.pageIndex,
        pageSize: data.pageSize,
      });
    } else {
      proxy.$message.error(msg);
    }
  };

  // 获取角色信息
  const getSysRoleInfo = async () => {
    const res = await getRole();
    roleList.value = res.data.list;
  };

  // 获取岗位信息
  const getSysPostInfo = async () => {
    const res = await getPost();
    postList.value = res.data.list;
  };

  // 获取部门树信息
  const getSysDeptTreeInfo = async () => {
    const res = await getDept();
    treeDeptData.value = res.data;
  };

  return {
    currentPage,
    getSysPostInfo,
    getSysRoleInfo,
    getSysDeptTreeInfo,
    getSysUserInfo,
  };
}

function useTableList() {
  // 部门数据
  const treeDeptData = ref();
  const roleList = ref([]);
  const postList = ref([]);

  // Table columns
  const columns = [
    { title: "编号", dataIndex: "userId" },
    { title: "登录名", dataIndex: "username" },
    { title: "昵称", dataIndex: "nickName" },
    { title: "部门", dataIndex: "deptName", slotName: "dept" },
    { title: "手机号", dataIndex: "phone" },
    { title: "状态", dataIndex: "status", slotName: "status" },
    { title: "创建时间", dataIndex: "createdAt", slotName: "createdAt" },
    { title: "操作", slotName: "action" },
  ];

  // Table Data
  const tableData = ref([]);

  /**
   * 分页改变
   * @param {Number} [page]
   */
  const handlePageChange = (page) => {
    pager.pageIndex = page;

    // 修改当前页码
    currentPage.value = page;
    getSysUserInfo({ ...pager, ...queryForm });
  };

  // 每页数据量
  const handlePageSizeChange = (pageSize) => {
    pager.pageSize = pageSize;
    getSysUserInfo({ ...pager, ...queryForm });
  };

  // 用户状态快速切换
  const handleSwitchChange = (record) => {
    proxy.$messageBox
      .confirm(
        `是否${record.status == 1 ? "停用" : "启用"} ${record.username} 用户？`,
        "注意",
        {
          confirmButtonText: "OK",
          cancelButtonText: "Cancel",
          type: "warning",
        }
      )
      .then(async () => {
        const params = { userId: record.userId, status: record.status };
        const res = await updateUserStatus(params);
        proxy.$message.success(res.msg);
      })
      .catch(() => {
        record.status = record.status == "2" ? "1" : "2";
      });
  };

  return {
    treeDeptData,
    roleList,
    postList,
    columns,
    tableData,
    handlePageChange,
    handlePageSizeChange,
    handleSwitchChange,
  };
}

function useModalOperate() {
  const modalVisible = ref(false);
  const modalTitle = ref("默认标题");

  // Form
  const modalForm = reactive({ status: "2" });

  // AddRules
  const rules = {
    nickName: [{ required: true, message: "请输入用户昵称" }],
    deptId: [{ required: true, message: "请选择所属部门" }],
    phone: [{ required: true, message: "请输入手机号" }],
    email: [
      { required: true, message: "请输入邮箱" },
      { type: "email", message: "请输入正确的邮箱格式" },
    ],
    username: [{ required: true, message: "请输入用户名称" }],
    password: [{ required: true, message: "请输入用户密码" }],
  };

  // Modal 取消后重置表单
  const handleModalCancel = () => {
    modalVisible.value = false;
    resetForm();
    modalForm.userId = null;
  };

  // 新增用户
  const handleAdd = () => {
    modalVisible.value = true;
    modalTitle.value = "新增用户";
  };

  /**
   * 修改用户
   * @param {Object} val
   */
  const handleUpdate = (val) => {
    modalVisible.value = true;
    Object.assign(modalForm, val);
  };

  const handleDelete = (val) => {
    deleteVisible.value = true;
    deleteData.value = [val.userId];
  };

  // 重置Form
  const resetForm = (formEl) => {
    if (!formEl) return;
    modalFormRef.value.resetFields();
  };

  // 表单提交
  const handleBeforeOk = (done) => {
    modalFormRef.value.validate(async (valid) => {
      if (valid) {
        if (!modalForm.userId) {
          const { code, msg } = await addUser(modalForm);
          if (code == 200) {
            proxy.$message.success("新增成功");
          } else {
            proxy.$message.error(msg);
          }
        } else {
          const { code, msg } = await updateUser(modalForm, modalForm.userId);
          if (code == 200) {
            proxy.$message.success("更新成功");
          } else {
            proxy.$message.error(msg);
          }
        }
        done();
        modalFormRef.value.resetFields();
        getSysUserInfo();
      } else {
        proxy.$message.error("表单校验失败");
        done(false);
      }
    });
  };

  return {
    rules,
    modalForm,
    modalVisible,
    modalTitle,
    handleAdd,
    handleUpdate,
    handleDelete,
    handleBeforeOk,
    handleModalCancel,
  };
}

onMounted(async () => {
  getSysUserInfo();
  getSysDeptTreeInfo();
  getSysRoleInfo();
  getSysPostInfo();
});
</script>

<style lang="scss">
@media screen and (max-width: 1720px) {
  .form-action {
    margin-top: 12px;
  }
}

.action {
  margin-bottom: 8px;
}
</style>
